/******************************************************************************************************
 * Author		:	Chester Ragel
 * Date			:	01 - March - 2007
 * Description	:	Helper methods taken from win32 API. This class also contains some structs 
 *					and enums from Win32. Most of them are taken from www.pinvoke.com
 * ****************************************************************************************************/

/*
 *  Context Menu Extention is the legal property of its developer
 *  Chester Ragel <chesterr@gmail.com> - Developer and Maintainer
 *	Sourceforge ID : chesterr
 *	Yahoo ID : chesterr1979 
 *	MSN : chesterr79@hotmail.com
 *	Gmail: chesterr@gmail.com
 *
 * If you want more information, found any bugs or have any doubts you 
 * can mail me or contact me through my yahoo id.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#region Namespace
using System;
using System.Text;
using System.Runtime.InteropServices;
#endregion

namespace Utils.ShellExtension.ContextMenu
{
	internal class Win32
	{

		#region Enums

		[Flags]
			internal enum GCSFlags 
		{
			GCS_HELPTEXTA = 1,
			GCS_HELPTEXTW = 5,
			GCS_UNICODE = 4,
			GCS_VALIDATEA = 2,
			GCS_VALIDATEW = 6,
			GCS_VERBA = 0,
			GCS_VERBW = 4
		}

		[Flags]
			internal enum ContextMenuFlag : uint
		{
			CMF_NORMAL		= 0x00000000,
			CMF_DEFAULTONLY	= 0x00000001,
			CMF_VERBSONLY	= 0x00000002,
			CMF_EXPLORE		= 0x00000004,
			CMF_NOVERBS		= 0x00000008,
			CMF_CANRENAME	= 0x00000010,
			CMF_NODEFAULT	= 0x00000020,
			CMF_INCLUDESTATIC= 0x00000040,
			CMF_RESERVED	= 0xffff0000
		}

		[Flags]
			internal enum MenuFlags : uint
		{
			MF_BYCOMMAND = 0,
			MF_BYPOSITION = 0x400,
			MF_CHECKED = 8,
			MF_DISABLED = 2,
			MF_ENABLED = 0,
			MF_GRAYED = 1,
			MF_HILITE = 0x80,
			MF_POPUP = 0x10,
			MF_SEPARATOR = 0x800,
			MF_STRING = 0,
			MF_UNCHECKED = 0
		}

		[Flags]
			internal enum DVASPECT
		{
			DVASPECT_CONTENT = 1,
			DVASPECT_THUMBNAIL = 2,
			DVASPECT_ICON = 4,
			DVASPECT_DOCPRINT = 8
		}

		internal enum CLIPFORMAT : uint
		{
			CF_TEXT =		1,
			CF_BITMAP =		2,
			CF_METAFILEPICT= 3,
			CF_SYLK =		4,
			CF_DIF =		5,
			CF_TIFF =		6,
			CF_OEMTEXT =	7,
			CF_DIB =		8,
			CF_PALETTE =	9,
			CF_PENDATA =	10,
			CF_RIFF =		11,
			CF_WAVE =		12,
			CF_UNICODETEXT= 13,
			CF_ENHMETAFILE= 14,
			CF_HDROP =		15,
			CF_LOCALE =		16,
			CF_MAX =		17,

			CF_OWNERDISPLAY=0x0080,
			CF_DSPTEXT =	0x0081,
			CF_DSPBITMAP =	0x0082,
			CF_DSPMETAFILEPICT= 0x0083,
			CF_DSPENHMETAFILE = 0x008E,

			CF_PRIVATEFIRST=0x0200,
			CF_PRIVATELAST=	0x02FF,

			CF_GDIOBJFIRST =0x0300,
			CF_GDIOBJLAST =	0x03FF
		}

		[Flags]
			internal enum TYMED
		{
			//     No data is being passed.
			TYMED_NULL = 0,
			//     The storage medium is a global memory handle (HGLOBAL). Allocate the global
			//     handle with the GMEM_SHARE flag. If the System.Runtime.Win32Services.ComTypes.STGMEDIUMSystem.Runtime.Win32Services.ComTypes.STGMEDIUM.pUnkForRelease
			//     member is null, the destination process should use GlobalFree to release
			//     the memory.
			TYMED_HGLOBAL = 1,
			//     The storage medium is a disk file identified by a path. If the STGMEDIUMSystem.Runtime.Win32Services.ComTypes.STGMEDIUM.pUnkForRelease
			//     member is null, the destination process should use OpenFile to delete the
			//     file.
			TYMED_FILE = 2,
			//     The storage medium is a stream object identified by an IStream pointer. Use
			//     ISequentialStream::Read to read the data. If the System.Runtime.Win32Services.ComTypes.STGMEDIUMSystem.Runtime.Win32Services.ComTypes.STGMEDIUM.pUnkForRelease
			//     member is not null, the destination process should use IStream::Release to
			//     release the stream component.
			TYMED_ISTREAM = 4,
			//     The storage medium is a storage component identified by an IStorage pointer.
			//     The data is in the streams and storages contained by this IStorage instance.
			//     If the System.Runtime.Win32Services.ComTypes.STGMEDIUMSystem.Runtime.Win32Services.ComTypes.STGMEDIUM.pUnkForRelease
			//     member is not null, the destination process should use IStorage::Release
			//     to release the storage component.
			TYMED_ISTORAGE = 8,
			//     The storage medium is a Graphics Device Interface (GDI) component (HBITMAP).
			//     If the System.Runtime.Win32Services.ComTypes.STGMEDIUMSystem.Runtime.Win32Services.ComTypes.STGMEDIUM.pUnkForRelease
			//     member is null, the destination process should use DeleteObject to delete
			//     the bitmap.
			TYMED_GDI = 16,
			//     The storage medium is a metafile (HMETAFILE). Use the Windows or WIN32 functions
			//     to access the metafile's data. If the System.Runtime.Win32Services.ComTypes.STGMEDIUMSystem.Runtime.Win32Services.ComTypes.STGMEDIUM.pUnkForRelease
			//     member is null, the destination process should use DeleteMetaFile to delete
			//     the bitmap.
			TYMED_MFPICT = 32,
			//     The storage medium is an enhanced metafile. If the System.Runtime.Win32Services.ComTypes.STGMEDIUMSystem.Runtime.Win32Services.ComTypes.STGMEDIUM.pUnkForRelease
			//     member is null, the destination process should use DeleteEnhMetaFile to delete
			//     the bitmap.
			TYMED_ENHMF = 64,
		}

		#endregion

		#region Structs

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
			internal struct CMINVOKECOMMANDINFO
		{
			public int cbSize;
			public uint fMask;
			public uint wnd;
			public int verb;
			[MarshalAs(UnmanagedType.LPStr)]
			public string parameters;
			[MarshalAs(UnmanagedType.LPStr)]
			public string directory;
			public int Show;
			public uint HotKey;
			public uint hIcon;
		}

		[StructLayout(LayoutKind.Sequential)]
			internal struct FORMATETC
		{
			public CLIPFORMAT	cfFormat;
			public uint			ptd;
			public DVASPECT		dwAspect;
			public int			lindex;
			public TYMED		tymed;
		}
		
		[StructLayout(LayoutKind.Sequential)]
			internal struct STGMEDIUM
		{
			public uint tymed;
			public uint hGlobal;
			public uint pUnkForRelease;
		}

		internal struct HMenu
		{
			public HMenu(IntPtr x) 
			{
				handle = x;
			}
			public IntPtr handle;
		}

		#endregion

		#region Interfaces
		[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), GuidAttribute("000214e8-0000-0000-c000-000000000046")]
			internal interface IShellExtInit
		{
			[PreserveSig()]
			int Initialize (IntPtr pidlFolder, IntPtr lpdobj, uint hKeyProgID);
		}

		[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), GuidAttribute("000214e4-0000-0000-c000-000000000046")]
			internal interface IContextMenu
		{
			[PreserveSig()]
			int	QueryContextMenu(HMenu hmenu, uint iMenu, uint idCmdFirst, int idCmdLast, Win32.ContextMenuFlag uFlags);
			[PreserveSig()]
			void InvokeCommand(ref CMINVOKECOMMANDINFO pici);
			[PreserveSig()]
			void GetCommandString(uint idCmd, uint uFlags, IntPtr pwReserved, IntPtr pszName, uint cchMax);
		}


		[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), GuidAttribute("0000010e-0000-0000-C000-000000000046")]
			internal interface IDataObject
		{
			[PreserveSig()]
			int GetData(ref FORMATETC a, ref STGMEDIUM b);
			[PreserveSig()]
			void GetDataHere(int a, ref STGMEDIUM b);
			[PreserveSig()]
			int QueryGetData(int a);
			[PreserveSig()]
			int GetCanonicalFormatEtc(int a, ref int b);
			[PreserveSig()]
			int SetData(int a, int b, int c);
			[PreserveSig()]
			int EnumFormatEtc(uint a, ref Object b);
			[PreserveSig()]
			int DAdvise(int a, uint b, Object c, ref uint d);
			[PreserveSig()]
			int DUnadvise(uint a);
			[PreserveSig()]
			int EnumDAdvise(ref Object a);
		}

		#endregion

		#region Methods

		[DllImport("user32")]
		internal static extern HMenu CreatePopupMenu();
		[DllImport("user32")]
		internal static extern bool AppendMenu(HMenu hmenu, MenuFlags uflags, IntPtr uIDNewItemOrSubmenu, string text);
		[DllImport("user32")]
		internal static extern bool InsertMenu(HMenu hmenu, int position, MenuFlags uflags, IntPtr uIDNewItemOrSubmenu, string text);
		[DllImport("shell32")]
		internal static extern uint DragQueryFile(IntPtr hDrop, uint iFile,[Out] StringBuilder lpszFile, uint cch);
		[DllImport("user32")]
		internal static extern bool SetMenuItemBitmaps(HMenu hmenu, int position, MenuFlags uflags, IntPtr hBitmapUnchecked, IntPtr hBitmapChecked);
        #endregion

	}
}
